<?php
/**
 * Class for parsing the comment blocks for classes, functions
 * methods and properties.
 *
 * The class parses the commentblock and extracts certain
 * documentation tags and the (full/small) description
 *
 * @author David Kingma
 * @version 0.1
 */
 
class commentParser{
    /**
     * @var string Contains the full commen text
     */
    public $comment;

    /**
     * @var object refence to the phpdoc(Class|Method|Property)
     */
    public $obj;

    /** @var boolean */
    public $smallDescriptionDone;
    
    /** @var boolean */
    public $fullDescriptionDone;

    /**
     * Constructor, initiateds the parse function
     *
     * @param string Commentaar block
     * @param string Defines if its the comment for a class, public of function
     */
    function __construct($comment,$obj){
        $this->comment=$comment;
        $this->obj=$obj;
        $this->parse();
    }
    /**
     * parses the comment, line for line
     *
     * Will take the type of comment (class, property or function) as an
     * argument and split it up in lines.
     * @param string Defines if its the comment for a class, public of function
     * @return void
     */
    function parse() {
        //reset object
        $descriptionDone = false;
        $this->fullDescriptionDone = false;

        //split lines
        $lines = split("\n",$this->comment);

        //check lines for description or tags
        foreach ($lines as $line) {
            $pos = strpos($line,"* @");
            if (trim($line) == "/**" || trim($line) == "*/") { //skip the start and end line
            }elseif (!($pos === false)) { //comment
                $this->parseTagLine(substr($line,$pos+3));
                $descriptionDone=true;
            }elseif(!$descriptionDone){
                $this->parseDescription($line);
            }
        }
        //if full description is empty, put small description in full description
        if (trim(str_replace(Array("\n","\r"), Array("",""), $this->obj->fullDescription)) == "")
            $this->obj->fullDescription = $this->obj->smallDescription;
    }

    /**
     * Parses the description to the small and full description properties
     *
     * @param string The description line
     * @return void
     */

     function parseDescription($descriptionLine){
        if(strpos($descriptionLine,"*")<=2) $descriptionLine=substr($descriptionLine,(strpos($descriptionLine,"*")+1));

         //geen lege comment regel indien al in grote omschrijving
         if(trim(str_replace(Array("\n","\r"),Array("",""),$descriptionLine))==""){
             if($this->obj->fullDescription=="")
                 $descriptionLine="";
            $this->smallDescriptionDone=true;
        }

        if(!$this->smallDescriptionDone)//add to small description
            $this->obj->smallDescription.=$descriptionLine;
        else{//add to full description
            $this->obj->fullDescription.=$descriptionLine;
        }
     }
     
    /**
     * Parses a tag line and extracts the tagname and values
     *
     * @param string The tagline
     * @return void
     */
    function parseTagLine($tagLine){
        $tagArr = explode(" ", $tagLine);
        $tag = $tagArr[0];

        switch(strtolower($tag)){
            case 'abstract':
                $this->obj->abstract=true; break;
            case 'access':
                $this->obj->isPrivate=(strtolower(trim($tagArr[1]))=="private")?true:false;
                break;
            case 'author':
                unset($tagArr[0]);
                $this->obj->author=implode(" ",$tagArr);
                break;
            case 'copyright':
                unset($tagArr[0]);
                $this->obj->copyright=implode(" ",$tagArr);
                break;
            case 'deprecated':
            case 'deprec':
                $this->obj->deprecated=true;
            case 'extends': break;
            case 'global':
                $this->obj->globals[]=$tagArr[1];
                break;
            case 'param':
                $o=new stdClass();
                $o->type=trim($tagArr[1]);
                $o->comment=implode(" ",$tagArr);
                $this->obj->params[]=$o;
                break;
            case 'return':
                $this->obj->return=trim($tagArr[1]); break;
            case 'link':break;
            case 'see':break;
            case 'since':
                $this->obj->since=trim($tagArr[1]); break;
            case 'static':
                $this->obj->static=true; break;
            case 'throws':
                unset($tagArr[0]);
                $this->obj->throws=implode(" ",$tagArr);
                break;
            case 'todo':
                unset($tagArr[0]);
                $this->obj->todo[]=implode(" ",$tagArr);
                break;
            case 'var':
                $this->obj->type=trim($tagArr[1]);
                unset($tagArr[0],$tagArr[1]);
                $comment=implode(" ",$tagArr);
                //check if its an optional property
                $this->obj->optional=strpos($comment,"[OPTIONAL]")!==FALSE;
                $this->obj->description=str_replace("[OPTIONAL]","",$comment);
                break;
            case 'version':
                $this->obj->version=$tagArr[1];
                break;
            default:
              //echo "\nno valid tag: '".strtolower($tag)."' at tagline: '$tagLine' <br>";
                //do nothing
        }
    }

}

?>